using System.ComponentModel;
using System.Runtime.Serialization;

using SharpGL.Enumerations;

namespace SharpGL.OpenGLAttributes
{
    /// <summary>
    /// This class has all the settings you can edit for fog.
    /// </summary>
    [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
    [DataContract(/*IsReference = true, */Name = "ScissorAttributes", Namespace = "SharpGL.SceneGraph")]
    public class ScissorAttributes : OpenGLAttributes
    {
        #region Private Consts

        private static readonly AttributeMask attributeMask = AttributeMask.Scissor;

        #endregion Private Consts

        #region Private Fields

        [DataMember()]
        private bool? enableScissorTest;
        [DataMember()]
        private int? scissorX;
        [DataMember()]
        private int? scissorY;
        [DataMember()]
        private int? scissorWidth;
        [DataMember()]
        private int? scissorHeight;

        #endregion Private Fields

        #region Protected Methods

        protected override void OnDeserializing()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Protected Methods

        #region Public Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ScissorAttributes"/> class.
        /// </summary>
        public ScissorAttributes()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Returns true if any attributes are set.
        /// </summary>
        /// <returns>
        /// True if any attributes are set
        /// </returns>
        public override bool AreAnyAttributesSet()
        {
            return
                enableScissorTest.HasValue ||
                scissorX.HasValue ||
                scissorY.HasValue ||
                scissorWidth.HasValue ||
                scissorHeight.HasValue;
        }

        /// <summary>
        /// Reset all attributes to unset state.
        /// </summary>
        public override void ResetAllAttributes()
        {
            enableScissorTest = null;
            scissorX = null;
            scissorY = null;
            scissorWidth = null;
            scissorHeight = null;
        }

        /// <summary>
        /// Sets the attributes.
        /// </summary>
        /// <param name="gl">The OpenGL instance.</param>
        public override void SetAttributes(OpenGL gl)
        {
            if (enableScissorTest.HasValue)
                gl.EnableIf(OpenGL.GL_SCISSOR_TEST, enableScissorTest.Value);
            if (scissorX.HasValue && scissorY.HasValue && scissorWidth.HasValue && scissorHeight.HasValue)
                gl.Scissor(scissorX.Value, scissorY.Value, scissorWidth.Value, scissorHeight.Value);

        }

        #endregion Public Methods

        #region Public Properties

        /// <summary>
        /// Gets or sets the enable scissor test.
        /// </summary>
        /// <value>
        /// The enable scissor test.
        /// </value>
        [Description("EnableScissorTest"), Category("Scissor attributes")]
        public bool? EnableScissorTest
        {
            get { return enableScissorTest; }
            set
            {
                if (enableScissorTest != value)
                {
                    enableScissorTest = value;

                    NotifyPropertyChanged("EnableScissorTest");
                }
            }
        }

        /// <summary>
        /// Gets or sets the scissor X.
        /// </summary>
        /// <value>
        /// The scissor X.
        /// </value>
        [Description("ScissorX"), Category("Scissor attributes")]
        public int? ScissorX
        {
            get { return scissorX; }
            set
            {
                if (scissorX != value)
                {
                    scissorX = value;

                    NotifyPropertyChanged("ScissorX");
                }
            }
        }

        /// <summary>
        /// Gets or sets the scissor Y.
        /// </summary>
        /// <value>
        /// The scissor Y.
        /// </value>
        [Description("ScissorY"), Category("Scissor attributes")]
        public int? ScissorY
        {
            get { return scissorY; }
            set
            {
                if (scissorY != value)
                {
                    scissorY = value;

                    NotifyPropertyChanged("ScissorY");
                }
            }
        }

        /// <summary>
        /// Gets or sets the width of the scissor.
        /// </summary>
        /// <value>
        /// The width of the scissor.
        /// </value>
        [Description("ScissorWidth"), Category("Scissor attributes")]
        public int? ScissorWidth
        {
            get { return scissorWidth; }
            set
            {
                if (ScissorWidth != value)
                {
                    ScissorWidth = value;

                    NotifyPropertyChanged("ScissorWidth");
                }
            }
        }

        /// <summary>
        /// Gets or sets the height of the scissor.
        /// </summary>
        /// <value>
        /// The height of the scissor.
        /// </value>
        [Description("ScissorHeight"), Category("Scissor attributes")]
        public int? ScissorHeight
        {
            get { return scissorHeight; }
            set
            {
                if (scissorHeight != value)
                {
                    scissorHeight = value;

                    NotifyPropertyChanged("ScissorHeight");
                }
            }
        }

        #endregion Public Properties
    }
}
